<?php
declare(strict_types=1);

namespace Lshorz\LaravelConfig;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Config\Repository;
use Lshorz\LaravelConfig\Events\Updated;
use Lshorz\LaravelConfig\Events\Destroy;

class DatabaseCfgHandler extends CfgHandlerAbstract implements CfgHandlerInterface
{
    /**
     * @var \Illuminate\Config\Repository;
     */
    protected Repository $config;

    /**
     * @var string
     */
    protected string $pk;

    /**
     * @var string
     */
    protected string $field_value;

    /**
     * @var string
     */
    protected string $field_identifier;

    /**
     * @var mixed
     */
    protected ?string $table;

    public function __construct(Repository $config)
    {
        $this->config = $config;
        $this->pk = $this->config->get('cfg.database.primary_key');
        $this->field_value = $this->config->get('cfg.database.field_value');
        $this->field_identifier = $this->config->get('cfg.database.field_identifier');

    }

    /**
     * 初始化配置
     *
     * @param string|null $identifier 文件名|配置名|keys
     * @return $this
     */
    public function init(?string $identifier = null): self
    {
        if ($identifier) {
            $this->setIdentifier($identifier, 'database');
        } else {
            $this->setIdentifier($this->config->get('cfg.default_identifier'), 'database');
        }

        $this->items = $this->getCfgItems();

        return $this;
    }

    /**
     * 验证配置
     *
     * @return bool
     */
    public function valid(): bool
    {
        return !empty($this->items);
    }

    /**
     * 获取配置列表
     *
     * @return array
     */
    public function index(): array
    {
        $results = $this->getModel()->select($this->pk, $this->field_identifier, 'created_at', 'updated_at')->get();
        if ($results->isNotEmpty()) {
            return $results->toArray();
        } else {
            return [];
        }
    }

    /**
     * 创建配置
     *
     * @param array $items ;
     * @return bool
     */
    public function create(array $items): bool
    {
        //检查是否存在同名的配置
        $model = $this->getModel()->where($this->field_identifier, '=', $this->getIdentifier())->first();

        if ($model instanceof Model) {
            return false;
        }

        $this->set($items);

        $model = $this->getModel();
        $model[$this->field_identifier] = $this->getIdentifier();
        $model[$this->field_value] = serialize($this->items);

        if ($model->save()) {
            event(new Updated($this->getIdentifier(), $this->items));
            $this->cacheDestroy();
            return true;
        } else {
            return false;
        }
    }

    /**
     * 更新配置
     *
     * @param string|null $key
     * @param mixed $value
     * @return bool
     */
    public function update(?string $key, $value): bool
    {
        if (is_null($key)) {
            $this->items = $value;
        } else {
            $this->set($key, $value);
        }

        return $this->store();
    }

    /**
     * 销毁配置
     *
     * @return bool
     */
    public function destroy(): bool
    {
        if ($this->getModel()->where($this->field_identifier, '=', $this->getIdentifier())->delete()) {
            $this->cacheDestroy();
            event(new Destroy($this->getIdentifier()));
            return true;
        } else {
            return false;
        }
    }

    /**
     * 保存配置
     *
     * @return bool
     */
    public function store(): bool
    {
        $model = $this->getModel()->where($this->field_identifier, '=', $this->getIdentifier())->first();

        if ($model instanceof Model) {
            $model[$this->field_value] = serialize($this->items);
            if ($model->save()) {
                event(new Updated($this->getIdentifier(), $this->items));
                $this->cacheDestroy();
                return true;
            }
        }

        return false;
    }

    /**
     * 设置配置值
     *
     * @param array|string $key
     * @param mixed $value
     * @return self
     */
    public function set($key, $value = null): self
    {
        return parent::set($key, $value);
    }

    /**
     * 将值插入到数组配置值前面
     *
     * @param string $key
     * @param mixed $value
     * @return self
     */
    public function prepend(string $key, $value): self
    {
        return parent::prepend($key, $value);
    }

    /**
     * 值插入到数组配置值后面
     *
     * @param string $key
     * @param mixed $value
     * @return self
     */
    public function push(string $key, $value): self
    {
        return parent::push($key, $value);
    }

    /**
     * 获取并初始化配置
     *
     * @return mixed
     */
    private function getCfgItems()
    {
        $result = $this->cacheGet() ?? [];

        if (empty($result)) {
            $model = $this->getModel()->where($this->field_identifier, '=', $this->getIdentifier())->first();

            if ($model instanceof Model) {
                $result = unserialize($model[$this->field_value]);
                if (is_array($result) && !empty($result)) {
                    $this->cacheCreate($result);
                }
            }
        }

        return $result;
    }

    /**
     * @return Model
     */
    private function getModel(): Model
    {
        return app($this->config->get('cfg.database.models'));
    }
}
